package J3_23;

import java.util.PriorityQueue;

public class MyTimer {
    //内部类表示创建的任务
    class Mytask implements Comparable<Mytask> {
        private Runnable runnable;
        // 为了⽅便后续判定, 使⽤绝对的时间戳.
        private long time;

        public Mytask(Runnable runnable, long delay) {
            this.runnable = runnable;
            // 取当前时刻的时间戳 + delay, 作为该任务实际执⾏的时间戳
            this.time =  System.currentTimeMillis() + delay;
        }

        //表示每个任务以到达时间以小到大排序
        // 这样的写法意味着每次取出的是时间最⼩的元素.
        @Override
        public int compareTo(Mytask o) {
            return (int)(this.time - o.time);
        }
    }
    // 核⼼结构
    private PriorityQueue<Mytask> queue = new PriorityQueue<>();
    // 创建⼀个锁对象
    private Object locker = new Object();

    //构造方法，创建线程
    Thread t;
    public MyTimer() {
        // 在这⾥构造线程, 负责执⾏具体任务了.
        t = new Thread( () -> {
            try {
                while (!Thread.currentThread().isInterrupted()) {
                    synchronized (locker) {
                        // 阻塞队列, 只有阻塞的⼊队列和阻塞的出队列, 没有阻塞的查看队⾸元素
                        while (queue.isEmpty()) {
                            locker.wait();
                        }
                        Mytask task = queue.peek();
                        long waitTime = task.time - System.currentTimeMillis();
                        if (waitTime <= 0) {
                            // 时间到了, 可以执⾏任务了
                            queue.poll();
                            task.runnable.run();
                        } else {
                            // 时间还没到
                            locker.wait(waitTime);
                        }
                    }
                }
            }catch (InterruptedException e) {
                    e.printStackTrace();
            }
        });
        t.start();
    }


    public void schedule(Runnable command, long after) {
        synchronized (locker) {
            Mytask mytack = new Mytask(command, after);
            //根据参数，插入队列
            queue.offer(mytack);
            locker.notify();
        }
    }

    //中断线程
    public void cancel() {
        t.interrupt();
        for (Mytask task : queue) {
            queue.remove(task);
        }
    }


    // 测试代码
    public static void main(String[] args) throws InterruptedException {
        MyTimer timer = new MyTimer();
        timer.schedule( ()->{
            System.out.println(2000);
        }, 2000);
        timer.schedule( () -> {
            System.out.println(1000);
        }, 1000);
        timer.schedule( ()->{
            System.out.println(3000);
        }, 3000);

        System.out.println(100);
        Thread.sleep(1500);
        timer.cancel();

    }
}
